#include "nvs_flash.h"
#include "nvs.h"
#include <stdio.h>

// 初始化NVS
esp_err_t init_nvs(void) {
    esp_err_t err = nvs_flash_init();
    if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        // 需要擦除并重新初始化
        ESP_ERROR_CHECK(nvs_flash_erase());
        err = nvs_flash_init();
    }
    return err;
}

// 保存结构体到NVS
esp_err_t save_struct_to_nvs(const char* namespace, const char* key, void* data,size_t size) {
    nvs_handle handle;
    esp_err_t err;
    
    // 打开NVS命名空间
    err = nvs_open(namespace, NVS_READWRITE, &handle);
    if (err != ESP_OK) return err;
    
    // 使用 nvs_set_blob 保存整个结构体
    err = nvs_set_blob(handle, key, data, size);
    if (err == ESP_OK) {
        // 提交更改确保数据持久化:cite[7]
        err = nvs_commit(handle);
    }
    
    nvs_close(handle);
    return err;
}

// 从NVS读取结构体
esp_err_t load_struct_from_nvs(const char* namespace, const char* key, void* data,size_t size) {
    nvs_handle handle;
    esp_err_t err;
    
    // 打开NVS命名空间
    err = nvs_open(namespace, NVS_READWRITE, &handle);
    if (err != ESP_OK) return err;
    
    // 首先获取blob的大小
    size_t required_size = 0;
    err = nvs_get_blob(handle, key, NULL, &required_size);
    if (err != ESP_OK || required_size != size) {
        nvs_close(handle);
        return err != ESP_OK ? err : ESP_ERR_NVS_INVALID_LENGTH;
    }
    
    // 读取数据到结构体
    err = nvs_get_blob(handle, key, data, &required_size);
    
    nvs_close(handle);
    return err;
}
/**
 * @brief 保存数组到NVS
 * @param namespace NVS命名空间
 * @param key 数据键名
 * @param array 数组指针
 * @param element_size 单个元素大小（字节）
 * @param count 数组元素个数
 * @return esp_err_t 错误码
 */
esp_err_t save_array_to_nvs(const char* namespace, const char* key, 
                           void* array, size_t element_size, size_t count) {
    nvs_handle handle;
    esp_err_t err;
    
    // 打开NVS命名空间
    err = nvs_open(namespace, NVS_READWRITE, &handle);
    if (err != ESP_OK) return err;
    
    // 计算总数据大小
    size_t total_size = element_size * count;
    
    // 保存数组数据
    err = nvs_set_blob(handle, key, array, total_size);
    if (err == ESP_OK) {
        // 保存数组元素个数（用于读取时验证）
        char count_key[32];
        snprintf(count_key, sizeof(count_key), "%s_count", key);
        nvs_set_u32(handle, count_key, count);
        
        // 提交更改
        err = nvs_commit(handle);
    }
    
    nvs_close(handle);
    return err;
}

/**
 * @brief 从NVS读取数组
 * @param namespace NVS命名空间
 * @param key 数据键名
 * @param array 数组指针（需要预先分配内存）
 * @param element_size 单个元素大小（字节）
 * @param max_count 数组最大容量（元素个数）
 * @return int 实际读取的元素个数，-1表示失败
 */
int load_array_from_nvs(const char* namespace, const char* key, 
                       void* array, size_t element_size, size_t max_count) {
    nvs_handle handle;
    esp_err_t err;
    
    // 打开NVS命名空间
    err = nvs_open(namespace, NVS_READWRITE, &handle);
    if (err != ESP_OK) return -1;
    
    // 读取保存的元素个数
    // char count_key[32];
    // snprintf(count_key, sizeof(count_key), "%s_count", key);
    // uint32_t saved_count = 0;
    // err = nvs_get_u32(handle, count_key, &saved_count);
    // if (err != ESP_OK) {
    //     nvs_close(handle);
    //     return -1;
    // }
    
    // // 确保不超过数组容量
    size_t read_count =  max_count;
    size_t total_size = element_size * read_count;
    
    // 读取数组数据
    err = nvs_get_blob(handle, key, array, &total_size);
    
    nvs_close(handle);
    return (err == ESP_OK) ? read_count : -1;
}

/**
 * @brief 检查数组是否存在
 * @param namespace NVS命名空间
 * @param key 数据键名
 * @return true 存在
 * @return false 不存在
 */
bool array_exists_in_nvs(const char* namespace, const char* key) {
    nvs_handle handle;
    esp_err_t err;
    
    err = nvs_open(namespace, NVS_READONLY, &handle);
    if (err != ESP_OK) return false;
    
    size_t required_size = 0;
    err = nvs_get_blob(handle, key, NULL, &required_size);
    
    nvs_close(handle);
    return (err == ESP_OK && required_size > 0);
}